/*
 * 提供一种使用参数作为维度层次关系，参数值作为层级字段的钻取、钻透方法
 */
_globalName = "HierarchyLink";

(function(global) {
    
    var globalName = window._globalName;
    
    try {
        delete window._globalName;
    } catch (e) {
        window._globalName = undefined;
    }

    var ConditionHandler = {
            param : function(name, value) {
                var result = {
                    type : 1,
                    colName : name,
                    operator : "E",
                    value : value
                };
                if (value == null) {
                    delete result.value;
                }
                return result;
            },

            // all args are conditions, only the first can be logic.
            add : function() {
                var length = arguments.length;
                if (length < 1) {
                    return;
                }
                
                var join = arguments[0]; 
                if (join == null || join.type !== 0 || join.logic !== 1) { // first is not "and"
                    join = {
                        type : 0,
                        logic : 1, // AND
                        child : []
                    };
                    arguments[0] != null && join.child.push(arguments[0]);
                };
                
                join.child = join.child || [];
                
                // 未考虑已存在的情况，直接添加
                for(var i = 1; i < length; i++) {
                    if (arguments[i] != null) {
                        join.child.push(arguments[i]);
                    }
                }
                return join;
            },
            
            // 1 level only
            remove : function(condition, name2remove) {
                if (condition == null || name2remove == null) {
                    return condition;
                }
                
                if (condition.type === 1 && condition.colName != undefined) {
                    if (name2remove === condition.colName) {
                        return null; // 空条件
                    } else {
                        return condition;
                    }
                }
                
                if (condition.type === 0 && condition.child != undefined) {
                    var children = condition.child;
                    for (var i=0; i < children.length; i++) {
                        var current = children[i];
                        if (current.type == 1 && current.colName === name2remove) {
                            children.splice(i, 1);
                            break;
                        }
                    }
                    if (children.length === 0) {
                        return null; // 空条件
                    } else {
                        condition.child = children;
                        return condition;
                    }
                    
                }
                
                if (condition.type > 1) {
                    return condition; // 无法且不需处理
                }
                
                throw "Illegal condition";
            }
            
    };
    
    var base64 = { //使用 ParamUtils base64 规则
            encode : function(str) {
                str = btoa(Utf8.encode(str));
//                str = str.replace(/\+/g, ".");
//                str = str.replace(/\//g, "_");
                
                return str;
            },
            decode : function(str) {
                str = str.replace(/\./g, "+");
                str = str.replace(/_/g, "/");
                        
                return Utf8.decode(atob(str));
            }
    };
    
    function getLevelDepth(levelName, hierarchy) {
        return hierarchy.indexOf(levelName);
    }
    
    function getNextLevel(levelName, hierarchy) {
        var index = hierarchy.indexOf(levelName);
        if (index >= 0 && index++ < hierarchy.length) {
            return hierarchy[index];
        }
    }
    
    function getPrevLevel(levelName, hierarchy) {
        var index = hierarchy.indexOf(levelName);
        if (index > 0) {
            return hierarchy[--index];
        }
    }
    
    function getPageParamJson() {
        var stateNode = document.getElementById("_paramState");
        var params = stateNode && stateNode.getAttribute("value") || base64.decode(document.getElementsByName("unieap_report_params")[0].value);
        return dojo.fromJson(params);
    }
    
    // co-前缀参数可选，用于在钻取时附带另外一组维度层次参数时使用
    function pushLevelTag(linkTags, paramName, paramValue, tagValue, coName, coValue) {
        if (linkTags == null) {
            linkTags = {};
        }
        
        var tagInfo = {name : paramValue, tag : tagValue};
        if (coName != null && coValue != null) {
            tagInfo.coName = coName;
            tagInfo.coValue = coValue;
        }
        
        var levelTags = linkTags[paramName];
        if (Object.prototype.toString.call(levelTags) == "[object Array]") {
            levelTags.push(tagInfo);
        } else {
            linkTags[paramName] = [tagInfo];
        }
        
        return linkTags;
    }
    
    function popLevelTag(linkTags, paramName) {
        if (linkTags == null) {
            return null;
        }
        
        var levelTags = linkTags[paramName];
        if (Object.prototype.toString.call(levelTags) == "[object Array]") {
            levelTags.splice(levelTags.length - 1, 1);
        } 
        
        return linkTags;
    }
    
    function backupParamInfo() {
        var levelsNode = document.getElementById("_paramState");
        if (levelsNode == null) {
            levelsNode = document.createElement("div");
            levelsNode.id = "_paramState";
            levelsNode.style.display = "none";
            levelsNode.style.position = "absolute";
            document.getElementsByName("unieap_report_params")[0].parentNode.appendChild(levelsNode);
        }
        
        levelsNode.setAttribute("value", dojo.toJson(getPageParamJson()));
    }
    
    function writeRequestParams(paramJson) {
        document.getElementsByName("unieap_report_params")[0].value = base64.encode(dojo.toJson(paramJson));
        document.getElementsByName("newReport")[0].value="false";
        document.getElementsByName("cachedId")[0].value="";
        document.getElementsByName("nPage")[0].value="1";
    }
    
    function submitDrill() {
        var resultForm = document.getElementById('resultForm');
        resultForm.target = "_self";
        resultForm.action = WEB_APP_NAME + '/Report-ResultAction.'+window.action_suffix;
        showProgressBar('true', resultForm);
        resultForm.submit();
    }
    
    function redirectReport(reportId, caption, paramJson) {
        var tempForm = document.createElement("form");
        tempForm.target = "_self";
        tempForm.method = "post";
        tempForm.action = WEB_APP_NAME + '/Report-ResultAction.'+window.action_suffix;
        
        tempForm.appendChild(getNode("reportId", encodeURIComponent(reportId)));
        tempForm.appendChild(getNode("unieap_report_params", base64.encode(dojo.toJson(paramJson))));
        tempForm.appendChild(getNode("newReport", "false"));
        
        // report navigation url logic
        var urNavLevels = [];
        urNavLevels.push(caption + ";1");
        tempForm.appendChild(getNode("ur_nav_levels", btoa(Utf8.encode(dojo.toJson(urNavLevels))).replace(/\+/g, '-').replace(/\//g, '_')));
        
        document.body.appendChild(tempForm);
        tempForm.submit();
        
        function getNode(name, value) {
            var input = document.createElement("input");
            input.type="hidden";
            input.name=name;
            input.value=value;
            return input;
        }
        
//      window.location.pathname=url;
    }

    // Exports below: 
    
    // 执行向下钻取 (co-前缀参数可选，用于在钻取时附带另外一组维度层次参数）
    global.link = function(event, paramName, paramValue, parentValue, hierarchy,
            coParamName, coParamValue, coHierarchy) {
        var content = (event.target || event.srcElement).innerHTML;
        var paramObj = getPageParamJson();
        var bizParams = dojo.fromJson(paramObj.unireport_biz_params);
        var conditionJson = bizParams.unireport_biz_params_sysreport;
        var depth = getLevelDepth(paramValue, hierarchy);
        if (depth < 0) {
            return; // 维度字段不在层级中，定义不合法。
        }
        var nextLevel = getNextLevel(paramValue, hierarchy);
        if (nextLevel == null) {
            console.info("No next level for param " + paramName);
            return;
        }
        
        conditionJson = ConditionHandler.add(conditionJson, 
                ConditionHandler.param(paramValue, parentValue));
        
        paramObj[paramName] = nextLevel;
        if (coParamName && coHierarchy) {
            paramObj[coParamName] = getNextLevel(coParamValue, coHierarchy);
        }
        if (conditionJson == null) {
            delete bizParams.unireport_biz_params_sysreport;
        } else {
            bizParams.unireport_biz_params_sysreport = conditionJson;
        }
        bizParams.paramHierarchyTags = pushLevelTag(bizParams.paramHierarchyTags, paramName, paramValue, content, coParamName, coParamValue);
        paramObj.unireport_biz_params = dojo.toJson(bizParams);
        
        backupParamInfo();
        writeRequestParams(paramObj);
        submitDrill();
        
    };
    
    // 执行向上钻取 (co-前缀参数可选，用于在钻取时附带另外一组维度层次参数）
    global.reverse = function(paramName, paramValue, hierarchy,
            coParamName, coParamValue, coHierarchy) {
        var paramObj = getPageParamJson();
        var bizParams = dojo.fromJson(paramObj.unireport_biz_params);
        var conditionJson = bizParams.unireport_biz_params_sysreport;
        var depth = getLevelDepth(paramValue, hierarchy);
        if (depth < 0) {
            return; // 维度字段不在层级中，定义不合法。
        }
        var prevLevel = getPrevLevel(paramValue, hierarchy);
        if (prevLevel == null) {
            console.info("No reverse level for param " + paramName);
            return;
        }
        
        conditionJson = ConditionHandler.remove(conditionJson, prevLevel);
        
        paramObj[paramName] = prevLevel;
        if (coParamName && coHierarchy) {
            paramObj[coParamName] = getPrevLevel(coParamValue, coHierarchy);
        }
        if (conditionJson == null) {
            delete bizParams.unireport_biz_params_sysreport;
        } else {
            bizParams.unireport_biz_params_sysreport = conditionJson;
        }
        bizParams.paramHierarchyTags = popLevelTag(bizParams.paramHierarchyTags, paramName);
        paramObj.unireport_biz_params = dojo.toJson(bizParams);
        
        backupParamInfo();
        writeRequestParams(paramObj);
        submitDrill();
        
    };
    
    // 执行钻透
    global.linkThrough = function(reportId, valuePair) {
        if (reportId == null || valuePair == null) {
            return;
        }
        
        var paramObj = getPageParamJson();
        var bizParams = dojo.fromJson(paramObj.unireport_biz_params);
        var caption = bizParams.caption;
        var conditionJson = bizParams.unireport_biz_params_sysreport;
        for (var name in valuePair) {
            conditionJson = ConditionHandler.add(conditionJson, 
                    ConditionHandler.param(name, valuePair[name]));
        }
        
//        bizParams.sourceReport=bizParams.reportId;
        bizParams.reportId=reportId;
        bizParams.caption=null;
        if (conditionJson == null) {
            delete bizParams.unireport_biz_params_sysreport;
        } else {
            bizParams.unireport_biz_params_sysreport = conditionJson;
        }
        delete bizParams.paramHierarchyTags;
        paramObj.unireport_biz_params = dojo.toJson(bizParams);
        
        redirectReport(reportId, caption, paramObj);
    };
    
    // 获得各维度参数的返回标签链接
    global.getTagLinks = function() {
        var paramObj = getPageParamJson();
        var bizParams = dojo.fromJson(paramObj.unireport_biz_params);
        
        var tagNodes = [];
        var tags = bizParams.paramHierarchyTags;
        if (tags != null) {
            for (var name in tags) { // for each param
                var node = document.createElement("span");
                node.name = "levelLink";
                
                var paramTags = tags[name];
                if (Object.prototype.toString.call(paramTags) == "[object Array]" 
                    && paramTags.length > 0) {// build fake hierarchy call: reverse(name, "" , [levelName, ""], coName, "", [coValue, ""]);
                    
                    var levelName = paramTags[paramTags.length - 1].name.replace(/\\/g, "\\\\").replace(/\"/, "\\\"");
                    var tag = paramTags[paramTags.length - 1].tag;// replace(/\&/g, "&amp;").replace(/\</g, "&lt;");
                    
                    if (paramTags[paramTags.length - 1].coName) { // has co-name and co-value
                        var coName = paramTags[paramTags.length - 1].coName.replace(/\\/g, "\\\\").replace(/\"/, "\\\"");
                        var coValue = paramTags[paramTags.length - 1].coValue.replace(/\\/g, "\\\\").replace(/\"/, "\\\"");
                        
                        node.innerHTML = "<a href='#' onclick='" + globalName + ".reverse(\"" + name + "\", \"\", [\""
                            + levelName + "\", \"\"], \"" + coName + "\", \"\", [\"" + coValue + "\", \"\"])'>" 
                            + (tag.length > 0 ? tag : "&nbsp;") + "</a>";
                    } else {
                        node.innerHTML = "<a href='#' onclick='" + globalName + ".reverse(\"" + name + "\", \"\", [\""
                            + levelName + "\", \"\"])'>" + (tag.length > 0 ? tag : "&nbsp;") + "</a>";
                    }

                    node.style.cssFloat="none";
                    node.style.styleFloat="none";
                    
                    tagNodes.push(node);
                }
            }
        }
        
        return tagNodes;
    };

    // 由于调用方法有所改动，以下两方法处理逻辑可能已不适用（需修改），且目前有替代方法，因此注掉
    
    // 当钻取到最内层时（不能再继续钻取），去掉下钻单元格鼠标悬置时的CSS样式
//    global.removeInnermostLinkStyle = function() {
//        // 先获取所有带clickable样式的单元格
//        var tds = document.getElementsByClassName('clickable');
//        dojo.forEach(tds, function(td) {
//            var funcStr = td.onclick.toString().trim();
//            // 获取单击此单元格时执行的代码的字符串形式
//            var s = funcStr.substring(funcStr.indexOf('{') + 1,
//                    funcStr.lastIndexOf('}') - 1).trim();
//            if (s.indexOf('HierarchyLink.link(') == 0) {
//                // 取第三个参数，即当前维度所在的层次
//                var level = eval(s.split(',', 3)[2]);
//                // 取最后一个参数，即当前维度所有层次列表。
//                var h = eval(s.substring(s.lastIndexOf('['), s.lastIndexOf(']') + 1));
//                if (level == h[h.length - 1]) {
//                    // 此时已位于最内层，去掉.clickable样式
//                    dojo.removeClass(td, 'clickable');
//                }
//            }
//        });
//    };
    
    // 当上卷到最外层时（不能再继续上卷），去掉上卷单元格鼠标悬置时的CSS样式
//    global.removeOutermostReverseStyle = function() {
//        // 先获取所有带clickable样式的单元格
//        var tds = document.getElementsByClassName('clickable');
//        dojo.forEach(tds, function(td) {
//            var funcStr = td.onclick.toString().trim();
//            // 获取单击此单元格时执行的代码的字符串形式
//            var s = funcStr.substring(funcStr.indexOf('{') + 1,
//                    funcStr.lastIndexOf('}') - 1).trim();
//            if (s.indexOf('HierarchyLink.reverse(') == 0) {
//                // 取第二个参数，即当前维度所在的层次
//                var level = eval(s.split(',', 2)[1]);
//                // 取最后一个参数，即当前维度所有层次列表。
//                var h = eval(s.substring(s.lastIndexOf('['), s.lastIndexOf(']') + 1));
//                if (level == h[0]) {
//                    // 此时已位于最外层，去掉.clickable样式
//                    dojo.removeClass(td, 'clickable');
//                }
//            }
//        });
//    };
    
})(window[_globalName] = window[_globalName] || {});